package org.proteored.miapeapi.xml.msi.adapter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import org.proteored.miapeapi.experiment.model.sort.SystemCoreManager;
import org.proteored.miapeapi.interfaces.Adapter;
import org.proteored.miapeapi.interfaces.msi.IdentifiedProtein;
import org.proteored.miapeapi.interfaces.msi.IdentifiedProteinSet;
import org.proteored.miapeapi.interfaces.msi.InputDataSet;
import org.proteored.miapeapi.interfaces.msi.InputParameter;
import org.proteored.miapeapi.xml.msi.autogenerated.InputDataSetReferences;
import org.proteored.miapeapi.xml.msi.autogenerated.MSIIdentifiedProteinSet;
import org.proteored.miapeapi.xml.msi.autogenerated.ObjectFactory;
import org.proteored.miapeapi.xml.msi.util.MSIControlVocabularyXmlFactory;
import org.proteored.miapeapi.xml.util.MiapeXmlUtil;
import org.proteored.miapeapi.xml.util.parallel.InnerIteratorSync;
import org.proteored.miapeapi.xml.util.parallel.InnerLock;

import uk.ac.ebi.jmzml.model.mzml.Spectrum;

public class IdentifiedProteinSetParallelAdapter implements
		Adapter<MSIIdentifiedProteinSet> {
	private final IdentifiedProteinSet proteinSet;
	private final ObjectFactory factory;
	private final MSIControlVocabularyXmlFactory cvFactory;

	public IdentifiedProteinSetParallelAdapter(IdentifiedProteinSet proteinSet,
			ObjectFactory factory, MSIControlVocabularyXmlFactory cvFactory) {
		this.cvFactory = cvFactory;
		this.factory = factory;
		this.proteinSet = proteinSet;
	}

	@Override
	public MSIIdentifiedProteinSet adapt() {
		MSIIdentifiedProteinSet proteinSetXML = factory
				.createMSIIdentifiedProteinSet();
		proteinSetXML.setName(proteinSet.getName());
		proteinSetXML.setFileURL(proteinSet.getFileLocation());

		Set<InputDataSet> inputDataSets = proteinSet.getInputDataSets();
		if (inputDataSets != null) {
			InputDataSetReferences inputDataSetRefs = factory
					.createInputDataSetReferences();
			for (InputDataSet inputDataSet : inputDataSets) {
				inputDataSetRefs.getInputDataSetRef().add(
						MiapeXmlUtil.IdentifierPrefixes.INPUTDATASET
								.getPrefix() + inputDataSet.getId());
			}
			proteinSetXML.setInputDataSetReferences(inputDataSetRefs);
		}
		InputParameter inputParameter = proteinSet.getInputParameter();
		if (inputParameter != null) {
			proteinSetXML
					.setParametersRef(MiapeXmlUtil.IdentifierPrefixes.PARAMETERS
							.getPrefix() + inputParameter.getId());
		}

		HashMap<String, IdentifiedProtein> identifiedProteins = proteinSet
				.getIdentifiedProteins();

		if (identifiedProteins != null) {
			int total = identifiedProteins.size();
			long t1 = System.currentTimeMillis();
			final Iterator<IdentifiedProtein> iterator = identifiedProteins
					.values().iterator();
			// Create lock.
			InnerLock lock = new InnerLock();
			InnerIteratorSync<Spectrum> iteratorSync = new InnerIteratorSync(
					iterator);
			Collection<InnerProteinAdapter> runners = new ArrayList<InnerProteinAdapter>();
			int processorCount = SystemCoreManager.getAvailableNumSystemCores();

			for (int i = 0; i < processorCount; i++) {
				// take current DB session
				InnerProteinAdapter runner = new InnerProteinAdapter(
						iteratorSync, lock, i, factory, cvFactory,
						proteinSetXML);
				runners.add(runner);
				new Thread(runner).start();
			}

			// Wait until all the processors ends
			lock.isDone(runners.size());

			// int i = 0;
			// for (IdentifiedProtein protein : identifiedProteins.values()) {
			// String proteinAcc = protein.getAccession();
			// i++;
			// log.info("Adapting protein ( " + i + "/" + total + ") " +
			// proteinAcc + " with "
			// + protein.getIdentifiedPeptides().size() + " peptides to XML");
			// int protein_id = -1;
			// if (protein instanceof UnidentifiedProtein == false) {
			// MSIIdentifiedProtein identifiedProteinXML = new
			// IdentifiedProteinAdapter(
			// protein, factory, cvFactory).adapt();
			// // save the protein_id to add it then in the peptides
			// protein_id =
			// MiapeXmlUtil.getIdFromXMLId(identifiedProteinXML.getId());
			// proteinSetXML.getMSIIdentifiedProtein().add(identifiedProteinXML);
			// }
			// /**
			// * Due to in the model the peptides are children of the protein,
			// this loop add to
			// * the peptideSet variable all the peptides that are found in the
			// protein
			// */
			// List<IdentifiedPeptide> identifiedPeptides =
			// protein.getIdentifiedPeptides();
			// if (identifiedPeptides != null) {
			// for (IdentifiedPeptide identifiedPeptide : identifiedPeptides) {
			// peptideSetXML.getMSIIdentifiedPeptide().add(
			// new IdentifiedPeptideAdapter(identifiedPeptide, protein_id,
			// factory, cvFactory).adapt());
			// }
			// }
			// }
		}
		return proteinSetXML;

	}

}
